<?php

namespace app\uniapp\service;

use app\common\exception\MiException;
use app\model\site\Site;
use app\model\site\User;
use app\uniapp\service\traits\InstanceTrait;
use think\db\exception\DataNotFoundException;
use think\db\exception\DbException;
use think\db\exception\ModelNotFoundException;
use think\db\Query;
use think\Model;

abstract class UniBaseService implements UniBaseInterface
{

    protected array $with = [];
    protected array $where = [];
    protected int $limit = 0;   // 限制查询数量
    protected string $order = '';
    protected bool $force = false;
    protected int|false $status = false;
    protected string|int|false $pkWhere = false;
    protected string $alias = '';

    protected int $siteId;
    protected int $userId;
    protected Model $model;
    public int|string $pk;  // 数据库表主键


    public function __construct()
    {
        try {
            $this->siteId = UniAuthService::instance()->getSiteId();
        }catch (MiException $e){
            $this->siteId = 0;
        }

        $this->userId = UniAuthService::instance()->getLoginId();

        $this->initialize();

        $this->pk = $this->model->getPk();
    }

    function query(): Query
    {
        return $this->makeQuery();
    }

    /**
     * @throws ModelNotFoundException
     * @throws DbException
     * @throws DataNotFoundException
     */
    public function find()
    {
        return $this->query()->find();
    }


    /**
     * @throws DbException
     */
    public function paginate($limit): \think\Paginator
    {
        return $this->query()->paginate($limit);
    }

    /**
     * @throws ModelNotFoundException
     * @throws DbException
     * @throws DataNotFoundException
     */
    public function select(): array|\think\Collection
    {
        return $this->query()->select();
    }

    public function setAlias($alias): static
    {
        $this->alias = $alias;
        return $this;
    }

    public function setPkWhere($key): self
    {
        $this->pkWhere = $key;
        return $this;
    }

    public function setWhere($where): static
    {
        $this->where = $where;
        return $this;
    }

    public function setLimit($limit): static
    {
        $this->limit = $limit;
        return $this;
    }

    public function setOrder($order): static
    {
        $this->order = $order;
        return $this;
    }

    public function setForce(bool $force): static
    {
        $this->force = $force;
        return $this;
    }

    public function setWith($with): static
    {
        $this->with = $with;
        return $this;
    }

    public function setStatus($status): static
    {
        $this->status = $status;
        return $this;
    }

    /**
     * @throws MiException
     */
    function create(array $data)
    {
        $data['site_id'] = $this->siteId;
        if (!$data['site_id']??''){
            throw new MiException("缺少站点ID");
        }
        return $this->model::class::create($this->formatData($data));
    }

    function update(array $data, array $where)
    {
        return $this->model::class::update($this->formatData($data), $where);
    }

    /**
     * @throws ModelNotFoundException
     * @throws DataNotFoundException
     * @throws DbException
     */
    function delete()
    {
        $query = $this->query();
        if ($this->force){
            $query->force();
        }
        $query->delete();
    }

    protected function makeQuery() : Query
    {

        // 每回查询都创建一个新的query
        $query = $this->model->newQuery();
        if ($this->alias){
            $query->alias($this->alias);
            $query->where("{$this->alias}.site_id", $this->siteId);
        }else{
            $query->where('site_id', $this->siteId);
        }


        if (count($this->with)){
            $query->with($this->with);
        }

        if (count($this->where)){
            $query->where($this->where);
        }

        if ($this->pkWhere != false){
            $query->where($this->pk, '=', $this->pkWhere);
        }

        if ($this->status !== false){
            $field = $this->alias ? "{$this->alias}.status" : "status";
            $query->where($field, '=', $this->status);
        }

        if ($this->limit > 0){
            $query->limit($this->limit);
        }

        if ($this->order) {
            $query->order($this->order);
        }

        return $query;
    }


}
